package tech.edwardvan.springsecuritydemo.security.config;

import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.vote.AffirmativeBased;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.expression.WebExpressionVoter;
import tech.edwardvan.springsecuritydemo.rbac.service.impl.RbacUserDetailServiceImpl;
import tech.edwardvan.springsecuritydemo.security.handler.JwtAccessDeniedHandler;
import tech.edwardvan.springsecuritydemo.security.handler.JwtAuthenticationEntryPoint;
import tech.edwardvan.springsecuritydemo.security.properties.JwtProperties;
import tech.edwardvan.springsecuritydemo.security.util.JwtTokenUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * 前后端分离Security 配置
 *
 * @author EdwardVan
 */
@Configuration
@EnableConfigurationProperties(JwtProperties.class)
@RequiredArgsConstructor
public class ApiSecurityConfig {

    private final JwtProperties jwtProperties;

    private final RbacUserDetailServiceImpl rbacUserDetailService;

    @Bean
    @Order(1)
    SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception {
        http.antMatcher("/api/**")
                .userDetailsService(rbacUserDetailService)
                //权限异常处理器
                .exceptionHandling(exception ->
                        exception.accessDeniedHandler(new JwtAccessDeniedHandler()).authenticationEntryPoint(new JwtAuthenticationEntryPoint()))
                // 禁用表单登录
                .formLogin(AbstractHttpConfigurer::disable)
                // 禁用退出登录
                .logout(AbstractHttpConfigurer::disable)
                // 禁用session
                .sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                // 禁用CSRF
                .csrf(AbstractHttpConfigurer::disable);
        //添加Jwt配置类
        http.apply(new JwtConfigurer());
        return http.build();
    }

    @Bean
    public JwtTokenUtil jwtTokenUtil() {
        return new JwtTokenUtil(this.jwtProperties);
    }

}
